home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / SCCVEC.ASM < prev    next >
Assembly Source File  |  1990-01-12  |  7KB  |  286 lines

  1. ; SCC interrupt handler for IBM-PC
  2.  
  3.     include pmacros.h
  4.  
  5. ; variables from C
  6.  
  7. dseg
  8. extvar    sccvecloc,word
  9. extvar    sccmaxvec,byte
  10. extvar    sccpolltab,word
  11. ifdef    LARGEDATA
  12. extvar    sccchan,dword
  13. else
  14. extvar    sccchan,word
  15. endif
  16. dsegend
  17.  
  18. ; variables from pcint.asm
  19.  
  20. dseg
  21. extvar    sssave,word
  22. extvar    spsave,word
  23. extvar    intstk,byte
  24. dsegend
  25.  
  26.     extproc doret
  27.  
  28. ; sccvec is the interrupt handler for SCC interrupts using INTACK
  29.  
  30.     pubproc sccvec
  31.  
  32.     cli            ; this code is not re-entrant, so make sure it
  33.                 ; is not interrupted. some multi-taskers
  34.                 ; intercept interrupt handlers, so be careful!
  35.  
  36.     push    ax        ; save ax first.
  37.     push    ds        ; save on user stack
  38.     getds
  39.     mov    ds,ax
  40.  
  41.     mov    sssave@,ss    ; stash user stack context
  42.     mov    spsave@,sp
  43.  
  44.     mov    ss,ax        ; set up interrupt stack
  45.     lea    sp,intstk@
  46.  
  47.     push    bx        ; save user regs on interrupt stack
  48.     push    cx
  49.     push    dx
  50.     push    bp
  51.     push    si
  52.     push    di
  53.     push    es
  54.  
  55. ifndef    LARGEDATA
  56.     mov    es,ax        ; small data assumes ES == DS
  57. endif
  58.  
  59. if    TURBO or MSC
  60.     cld            ; in case "movsb" or "movsw" is used
  61. endif
  62.  
  63. ; Read SCC interrupt vector and check it
  64.  
  65. sccint: mov    dx,sccvecloc@
  66.     out    dx,al        ; Generate INTACK
  67.     jmp    short d1    ; Delay
  68. d1:    jmp    short d2
  69. d2:    jmp    short d3
  70. d3:    in    al,dx        ; Read the vector
  71.     cmp    al,sccmaxvec@    ; Check for a legal vector
  72.     jnc    clrret        ; It should not be >= the maximum
  73.                 ; If it is, ignore the interrupt
  74.  
  75. ; Extract channel number and status from vector. Determine handler address.
  76.  
  77.     mov    bl,al        ; Copy vector (need it later for status)
  78.     shr    bl,1        ; Discard least significant bit
  79.     jc    clrret        ; It should not be a 1
  80.     and    bx,7ch        ; Isolate channel number (and make word)
  81.     xor    bl,04h        ; Toggle A/B channel bit
  82. ifdef    LARGEDATA
  83.     les    si,sccchan@[bx] ; Read address of channel structure
  84. else
  85.     shr    bl,1        ; Discard another bit
  86.     mov    si,sccchan@[bx] ; Read address of channel structure
  87. endif
  88.     test    si,si        ; Test for NULL
  89.     je    clrret        ; No channel struct, ignore it
  90.     and    ax,06h        ; Isolate status info from vector
  91.     add    ax,ax        ; Make index in FAR PTR array
  92.     mov    bx,ax        ; It must be in BX
  93.  
  94. ; Call the handler (defined in C), with sccchan struct as a parameter
  95.  
  96.     pushes
  97.     push    si        ; Put channel struct as a parameter
  98. ifdef    LARGEDATA
  99.     call    dword ptr es:[bx+si] ; Call the handler
  100. else
  101.     call    dword ptr [bx+si]    ; Call the handler
  102. endif
  103.     pop    si        ; Get channel struct back
  104.     popes
  105.  
  106. ; Reset highest priority interrupt
  107.  
  108. ifdef    LARGEDATA
  109.     mov    dx,es:16[si]    ; Get control register address
  110. else
  111.     mov    dx,16[si]    ; Get control register address
  112. endif
  113.     mov    al,38h        ; "Reset Highest IUS" opcode
  114.     out    dx,al        ; to WR0
  115.     jmp    short d4    ; settling delay
  116. d4:    jmp    short d5
  117. d5:
  118.  
  119. ; Determine if more interrupt requests are coming in from the SCCs
  120.  
  121.     jmp    sccint        ; keep trying until no vector returned
  122.  
  123. ; Clear the ISR bit in the PIC and return from interrupt
  124.  
  125. clrret: jmp    doret@        ; execute code in pcint.asm
  126.  
  127.     pend    sccvec
  128.  
  129. ; sccnovec is the interrupt handler for SCC interrupts using polling
  130.  
  131.     pubproc sccnovec
  132.  
  133.     cli            ; this code is not re-entrant, so make sure it
  134.                 ; is not interrupted. some multi-taskers
  135.                 ; intercept interrupt handlers, so be careful!
  136.  
  137.     push    ax        ; save ax first.
  138.     push    ds        ; save on user stack
  139.     getds
  140.     mov    ds,ax
  141.  
  142.     mov    sssave@,ss    ; stash user stack context
  143.     mov    spsave@,sp
  144.  
  145.     mov    ss,ax        ; set up interrupt stack
  146.     lea    sp,intstk@
  147.  
  148.     push    bx        ; save user regs on interrupt stack
  149.     push    cx
  150.     push    dx
  151.     push    bp
  152.     push    si
  153.     push    di
  154.     push    es
  155.  
  156. ifndef    LARGEDATA
  157.     mov    es,ax        ; small data assumes ES == DS
  158. endif
  159.  
  160. if    TURBO or MSC
  161.     cld            ; in case "movsb" or "movsw" is used
  162. endif
  163.  
  164. ; Find the SCC generating the interrupt by polling all attached SCCs
  165. ; reading RR3A (the interrupt pending register)
  166.  
  167. sccintnv:
  168.     lea    si,sccpolltab@    ; Point to polling table
  169. sccpoll:
  170.     mov    dx,[si]        ; Get chan A CTRL address
  171.     inc    si
  172.     inc    si
  173.     test    dx,dx        ; End of table without finding it
  174.     je    clrret        ; Then return from interrupt
  175.     mov    al,3        ; Select RR3A
  176.     out    dx,al
  177.     jmp    short d6    ; Delay
  178. d6:    jmp    short d7
  179. d7:    jmp    short d8
  180. d8:    in    al,dx
  181.     test    al,al        ; Test if a nonzero IP here
  182.     jnz    sccip        ; Yes, handle it
  183.     inc    si        ; No, next A CTRL
  184.     inc    si
  185.     jmp    sccpoll
  186.  
  187. ; Read SCC interrupt vector from RR2B, it should always be correct
  188. ; Extract channel number and status from vector. Determine handler address.
  189.  
  190. sccip:    mov    dx,[si]        ; Read B CTRL address
  191.     mov    al,2        ; Select RR2B
  192.     out    dx,al
  193.     jmp    short d9    ; Delay
  194. d9:    jmp    short d10
  195. d10:    jmp    short d11
  196. d11:    in    al,dx        ; Read the vector
  197.     mov    bl,al        ; Copy vector (need it later for status)
  198.     shr    bl,1        ; Discard least significant bit
  199.     and    bx,7ch        ; Isolate channel number (and make word)
  200.     xor    bl,04h        ; Toggle A/B channel bit
  201. ifdef    LARGEDATA
  202.     les    si,sccchan@[bx] ; Read address of channel structure
  203. else
  204.     shr    bl,1        ; Discard another bit (sccchan=words)
  205.     mov    si,sccchan@[bx] ; Read address of channel structure
  206. endif
  207.     test    si,si        ; Test for NULL
  208.     je    clrret        ; No channel struct, ignore it
  209.     and    ax,06h        ; Isolate status info from vector
  210.     add    ax,ax        ; Make index in FAR PTR array
  211.     mov    bx,ax        ; It must be in BX
  212.  
  213. ; Call the handler (defined in C), with sccchan struct as a parameter
  214.  
  215.     pushes
  216.     push    si        ; Put channel struct as a parameter
  217. ifdef    LARGEDATA
  218.     call    dword ptr es:[bx+si] ; Call the handler
  219. else
  220.     call    dword ptr [bx+si]    ; Call the handler
  221. endif
  222.     pop    si        ; Remove parameter from stack
  223.     popes
  224.  
  225. ; Check for more interrupt pending bits
  226.  
  227.     jmp    sccintnv
  228.  
  229.     pend    sccnovec
  230.  
  231. ; scctvec is called as the replacement timer tick interrupt handler every 55ms.
  232. ; it calls scctim() and then jumps to the original handler.
  233. ; when the constant SCC_HWTIMER is defined during compilation of SCC.C,
  234. ; we'll install it directly on the timer hardware interrupt, not on the
  235. ; timer-tick user-exit (int 1c) because some programs take over that one
  236. ; without saving and calling the original handler installed there...
  237. ; (also, Phil Karn points out the int 1c is sluggish when DoubleDos is running)
  238.  
  239.     extproc scctim
  240.  
  241.     pubproc scctvec
  242.  
  243.     cli            ; this code is not re-entrant, so make sure it
  244.                 ; is not interrupted. some multi-taskers
  245.                 ; intercept interrupt handlers, so be careful!
  246.  
  247.     push    ax        ; save ax first.
  248.     push    ds        ; save on user stack
  249.     getds
  250.     mov    ds,ax
  251.  
  252.     mov    sssave@,ss    ; stash user stack context
  253.     mov    spsave@,sp
  254.  
  255.     mov    ss,ax        ; set up interrupt stack
  256.     lea    sp,intstk@
  257.  
  258.     push    bx        ; save user regs on interrupt stack
  259.     push    cx        ; (only those not saved by C)
  260.     push    dx
  261.     push    es
  262.  
  263. ifndef    LARGEDATA
  264.     mov    es,ax        ; small data assumes ES == DS
  265. endif
  266.  
  267.     call    scctim@        ; call timer tick routine (in C)
  268.  
  269.     pop    es        ; restore everything
  270.     pop    dx
  271.     pop    cx
  272.     pop    bx
  273.  
  274.     mov    ss,sssave@
  275.     mov    sp,spsave@    ; restore original stack context
  276.     pop    ds
  277.     pop    ax
  278.  
  279.     db    0eah        ; opcode for a far jump
  280.     pubvar    sccotvec,<dw 0,0ffffh>    ; original INT handler address
  281.                 ; is stored here by initialization code
  282.  
  283.     pend    scctvec
  284.  
  285.     end
  286.